package effectivejava.chapter3.item13;

import java.util.Objects;

/**
 * @author baicaixiaozhan
 * @since 2020/9/16
 */
public class CloneableDemo {

    public static void main(String[] args) throws CloneNotSupportedException {
        // objectClone();

        equalsInObjectClone();
    }

    private static void equalsInObjectClone() throws CloneNotSupportedException {
        CloneableObj source = new CloneableObj();
        source.setValue("zhangsan");

        CloneableObj clone = (CloneableObj) source.clone();

        // false
        System.out.println("clone == source : " + (clone == source));
        // true
        System.out.println("clone.value == source.value : " + (clone.getValue() == source.getValue()));
        // true, 这里对比的是对象本身, 不是对象引用地址
        System.out.println("clone.equals(source) : " + (clone.equals(source)));
    }


    public static void objectClone() throws CloneNotSupportedException {
        NonCloneableObj nonCloneableObj = new NonCloneableObj();
        // 不实现 Cloneable 接口 , 进行 clone 会抛出 CloneNotSupportedException
        nonCloneableObj.clone();

        // 正常 clone
        CloneableObj cloneableObj = new CloneableObj();
        cloneableObj.clone();
    }

    public static class NonCloneableObj {
        private int id;
        // get && set ...

        /**
         * 修改 object.clone() protected => public 访问权限
         *
         * @return
         * @throws CloneNotSupportedException
         */
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    public static class CloneableObj implements Cloneable {
        private String value;

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        /**
         * 修改 object.clone() protected => public 访问权限
         *
         * @return
         * @throws CloneNotSupportedException
         */
        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            CloneableObj that = (CloneableObj) o;
            return Objects.equals(value, that.value);
        }

        @Override
        public int hashCode() {
            return Objects.hash(value);
        }
    }
}
